package org.jeecg.modules.demo.timeline.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jeecg.modules.demo.patent.entity.Patent;
import org.jeecg.modules.demo.timeline.entity.PatentTimeline;
import org.jeecg.modules.demo.timeline.mapper.PatentTimelineMapper;
import org.jeecg.modules.demo.patent.service.IPatentService;
import org.jeecg.modules.demo.timeline.service.IPatentTimelineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * @Description: 专利时间脉络表
 * @Author: jeecg-boot
 * @Date: 2025-01-15
 * @Version: V1.0
 */
@Service
@Slf4j
public class PatentTimelineServiceImpl extends ServiceImpl<PatentTimelineMapper, PatentTimeline> implements IPatentTimelineService {

    @Autowired
    private PatentTimelineMapper patentTimelineMapper;
    
    @Autowired
    private IPatentService patentService;

    @Override
    public List<Map<String, Object>> getTimelineData(String startDate, String endDate, 
                                                    String eventType, String inventor, String institution) {
        QueryWrapper<PatentTimeline> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("event_status", "ACTIVE");
        
        if (startDate != null && !startDate.isEmpty()) {
            queryWrapper.ge("event_date", startDate);
        }
        if (endDate != null && !endDate.isEmpty()) {
            queryWrapper.le("event_date", endDate);
        }
        if (eventType != null && !eventType.isEmpty()) {
            queryWrapper.eq("event_type", eventType);
        }
        
        queryWrapper.orderByDesc("event_date", "sort_order");
        // 性能优化：限制返回数量，避免查询过多数据导致超时
        queryWrapper.last("LIMIT 500");
        
        List<PatentTimeline> timelineList = this.list(queryWrapper);
        
        // 性能优化：批量查询专利信息，避免 N+1 查询问题
        List<String> patentIdList = new ArrayList<>();
        for (PatentTimeline timeline : timelineList) {
            patentIdList.add(timeline.getPatentId());
        }
        
        // 批量获取专利信息
        Map<String, Patent> patentMap = new HashMap<>();
        if (!patentIdList.isEmpty()) {
            List<Patent> patentList = patentService.listByIds(patentIdList);
            for (Patent patent : patentList) {
                patentMap.put(patent.getId(), patent);
            }
        }
        
        // 转换为前端需要的格式
        List<Map<String, Object>> resultList = new ArrayList<>();
        for (PatentTimeline timeline : timelineList) {
            Map<String, Object> itemMap = new HashMap<>();
            itemMap.put("id", timeline.getId());
            itemMap.put("patentId", timeline.getPatentId());
            itemMap.put("date", timeline.getEventDate());
            itemMap.put("type", getEventTypeName(timeline.getEventType()));
            itemMap.put("title", timeline.getEventTitle());
            itemMap.put("description", timeline.getEventDescription());
            itemMap.put("sortOrder", timeline.getSortOrder());
            
            // 从缓存的 Map 中获取专利详细信息
            Patent patent = patentMap.get(timeline.getPatentId());
            if (patent != null) {
                itemMap.put("applyId", patent.getApplyId());
                itemMap.put("applyPublicId", patent.getApplyPublicId());
                itemMap.put("inventor", patent.getInventorZhName() != null ? patent.getInventorZhName() : patent.getInventorOriginName());
                itemMap.put("institution", patent.getApplyInstitutionZhName() != null ? patent.getApplyInstitutionZhName() : patent.getApplyInstitutionOriginName());
                itemMap.put("ipcClass", patent.getIpcClassId());
                itemMap.put("summary", patent.getSummaryZh() != null ? patent.getSummaryZh() : patent.getSummary());
            }
            
            resultList.add(itemMap);
        }
        
        return resultList;
    }

    @Override
    public Map<String, Object> getTimelineStatistics(String startDate, String endDate, 
                                                    String eventType, String inventor, String institution) {
        // 性能优化：简化统计查询，避免多次数据库查询
        Map<String, Object> stats = new HashMap<>();
        
        // 基础统计
        QueryWrapper<PatentTimeline> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("event_status", "ACTIVE");
        
        if (startDate != null && !startDate.isEmpty()) {
            queryWrapper.ge("event_date", startDate);
        }
        if (endDate != null && !endDate.isEmpty()) {
            queryWrapper.le("event_date", endDate);
        }
        if (eventType != null && !eventType.isEmpty()) {
            queryWrapper.eq("event_type", eventType);
        }
        
        // 总事件数
        long totalEvents = this.count(queryWrapper);
        stats.put("totalEvents", totalEvents);
        
        // 申请事件数
        QueryWrapper<PatentTimeline> applyQuery = new QueryWrapper<>();
        applyQuery.eq("event_status", "ACTIVE");
        if (startDate != null && !startDate.isEmpty()) {
            applyQuery.ge("event_date", startDate);
        }
        if (endDate != null && !endDate.isEmpty()) {
            applyQuery.le("event_date", endDate);
        }
        if (eventType != null && !eventType.isEmpty()) {
            applyQuery.eq("event_type", eventType);
        }
        applyQuery.eq("event_type", "APPLY");
        long applicationCount = this.count(applyQuery);
        stats.put("applicationCount", applicationCount);
        
        // 公布事件数
        QueryWrapper<PatentTimeline> publishQuery = new QueryWrapper<>();
        publishQuery.eq("event_status", "ACTIVE");
        if (startDate != null && !startDate.isEmpty()) {
            publishQuery.ge("event_date", startDate);
        }
        if (endDate != null && !endDate.isEmpty()) {
            publishQuery.le("event_date", endDate);
        }
        if (eventType != null && !eventType.isEmpty()) {
            publishQuery.eq("event_type", eventType);
        }
        publishQuery.eq("event_type", "PUBLISH");
        long publicationCount = this.count(publishQuery);
        stats.put("publicationCount", publicationCount);
        
        // 总专利数（去重）
        QueryWrapper<PatentTimeline> patentQuery = new QueryWrapper<>();
        patentQuery.eq("event_status", "ACTIVE");
        if (startDate != null && !startDate.isEmpty()) {
            patentQuery.ge("event_date", startDate);
        }
        if (endDate != null && !endDate.isEmpty()) {
            patentQuery.le("event_date", endDate);
        }
        if (eventType != null && !eventType.isEmpty()) {
            patentQuery.eq("event_type", eventType);
        }
        patentQuery.select("DISTINCT patent_id");
        long totalPatents = this.count(patentQuery);
        stats.put("totalPatents", totalPatents);
        
        return stats;
    }

    @Override
    @Transactional
    public void generateTimelineData() {
        try {
            log.info("开始生成时间脉络数据...");
            
            // 先检查是否已有数据，如果有则跳过
            long existingCount = this.count(new QueryWrapper<>());
            if (existingCount > 0) {
                log.info("时间脉络数据已存在，跳过生成。现有数据量: {}", existingCount);
                return;
            }
            
            // 分批处理，避免长时间锁表
            int batchSize = 100;
            int offset = 0;
            int totalProcessed = 0;
            
            while (true) {
                // 分批获取专利数据
                QueryWrapper<Patent> patentQuery = new QueryWrapper<>();
                patentQuery.last("LIMIT " + batchSize + " OFFSET " + offset);
                List<Patent> patentBatch = patentService.list(patentQuery);
                
                if (patentBatch.isEmpty()) {
                    break;
                }
                
                List<PatentTimeline> timelineBatch = new ArrayList<>();
                
                for (Patent patent : patentBatch) {
                    // 申请日时间节点
                    if (patent.getApplyDate() != null) {
                        PatentTimeline applyTimeline = new PatentTimeline();
                        applyTimeline.setId(java.util.UUID.randomUUID().toString().replace("-", ""));
                        applyTimeline.setPatentId(patent.getId());
                        applyTimeline.setEventType("APPLY");
                        applyTimeline.setEventDate(patent.getApplyDate());
                        applyTimeline.setEventTitle("专利申请");
                        applyTimeline.setEventDescription("专利《" + 
                            (patent.getZhName() != null ? patent.getZhName() : patent.getOriginName()) + "》提交申请");
                        applyTimeline.setEventStatus("ACTIVE");
                        applyTimeline.setSortOrder(1);
                        applyTimeline.setCreateTime(new Date());
                        timelineBatch.add(applyTimeline);
                    }
                    
                    // 申请公布日时间节点
                    if (patent.getApplyPublicDate() != null) {
                        PatentTimeline publishTimeline = new PatentTimeline();
                        publishTimeline.setId(java.util.UUID.randomUUID().toString().replace("-", ""));
                        publishTimeline.setPatentId(patent.getId());
                        publishTimeline.setEventType("PUBLISH");
                        publishTimeline.setEventDate(patent.getApplyPublicDate());
                        publishTimeline.setEventTitle("专利申请公布");
                        publishTimeline.setEventDescription("专利《" + 
                            (patent.getZhName() != null ? patent.getZhName() : patent.getOriginName()) + "》申请公布");
                        publishTimeline.setEventStatus("ACTIVE");
                        publishTimeline.setSortOrder(2);
                        publishTimeline.setCreateTime(new Date());
                        timelineBatch.add(publishTimeline);
                    }
                }
                
                // 批量保存当前批次
                if (!timelineBatch.isEmpty()) {
                    this.saveBatch(timelineBatch);
                    totalProcessed += patentBatch.size();
                    log.info("已处理专利批次: {}, 当前批次专利数: {}, 生成事件数: {}", 
                        offset / batchSize + 1, patentBatch.size(), timelineBatch.size());
                }
                
                offset += batchSize;
                
                // 如果当前批次小于批次大小，说明已经处理完所有数据
                if (patentBatch.size() < batchSize) {
                    break;
                }
            }
            
            log.info("时间脉络数据生成完成，共处理专利: {}, 生成事件总数: {}", 
                totalProcessed, this.count(new QueryWrapper<>()));
                
        } catch (Exception e) {
            log.error("生成时间脉络数据失败", e);
            throw e;
        }
    }

    @Override
    public List<Map<String, Object>> getYearDistribution(String startDate, String endDate) {
        return patentTimelineMapper.getYearDistribution(startDate, endDate);
    }

    @Override
    public List<Map<String, Object>> getInstitutionStats(String startDate, String endDate) {
        return patentTimelineMapper.getInstitutionStats(startDate, endDate);
    }

    @Override
    public List<Map<String, Object>> getInventorStats(String startDate, String endDate) {
        return patentTimelineMapper.getInventorStats(startDate, endDate);
    }
    
    @Override
    @Transactional
    public void clearTimelineData() {
        try {
            log.info("开始清理时间脉络数据...");
            this.remove(new QueryWrapper<>());
            log.info("时间脉络数据清理完成");
        } catch (Exception e) {
            log.error("清理时间脉络数据失败", e);
            throw e;
        }
    }
    
    /**
     * 获取事件类型名称
     */
    private String getEventTypeName(String eventType) {
        switch (eventType) {
            case "APPLY":
                return "申请";
            case "PUBLISH":
                return "公布";
            case "GRANT":
                return "授权";
            case "REJECT":
                return "驳回";
            default:
                return eventType;
        }
    }
}

